﻿//========================================================= 
/**@file MagneticCmdDriver.h
 * @brief 磁条命令驱动
 * 
 * @date 2016-06-12   17:08:47
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_MAGNETICCMDDRIVER_H_
#define _LIBZHOUYB_MAGNETICCMDDRIVER_H_
//--------------------------------------------------------- 
#include "../CommonCmdDriver.h"

#include "../../../device/magnetic/MagneticDevAdapter.h"
using zhou_yb::device::magnetic::MagneticDevAdapter;

#include "../../../extension/ability/TimerDevAdapter.h"
using zhou_yb::extension::ability::TimerDevAdapter;
//--------------------------------------------------------- 
namespace zhou_yb {
namespace application {
namespace driver {
//--------------------------------------------------------- 
/// 磁条命令驱动
class MagneticCmdDriver : 
    public CommonCmdDriver, 
    public BaseDevAdapterBehavior<IInteractiveTrans>
{
protected:
    TimerDevAdapter _timerAdapter;
    MagneticDevAdapter _magAdapter;
public:
    MagneticCmdDriver() : CommonCmdDriver()
    {
        _errGetter.Add(_magAdapter).Select("TimeReader", _timerAdapter);

        select_helper<LoggerSetter::SelecterType>::select(_logSetter),
            _timerAdapter, _magAdapter;

        _timerAdapter.IsTryWrite = false;
        _magAdapter.SelectDevice(_timerAdapter);

        _RegisteCMD(MagneticCmdDriver, MagSetting);
        _RegisteCMD(MagneticCmdDriver, MagRead);
        _RegisteCMD(MagneticCmdDriver, MagWrite);
        _RegisteCMD(MagneticCmdDriver, MagClear);

        _RegisteCancelCMD(MagneticCmdDriver);
        _RegisteAdapterCMD(MagneticCmdDriver);
    }
    LC_CMD_CANCEL(_timerAdapter);
    LC_CMD_ADAPTER_INVOKE(IInteractiveTrans, _timerAdapter);
    /**
     * @brief 设置磁条参数
     * @date 2016-06-12 17:17
     *
     * @param [in] IsHigh : bool 是否为高抗
     * @param [in] Tr2Bpi : uint 二磁道BPI
     * @param [in] TrElectric : uint 写磁头电流
     */
    LC_CMD_METHOD(MagSetting)
    {
        string setting;
        if(arg.Get("IsHigh", setting))
        {
            bool isHigh = ArgConvert::FromString<bool>(setting);
            MagneticDevAdapter::ImpedanceMode mode = isHigh ? MagneticDevAdapter::HighImpedance : MagneticDevAdapter::LowImpedance;
            if(!MagneticDevAdapter::SetImpedanceMode(_pDev, mode))
            {
                _logErr(DeviceError::OperatorErr, "设置高低抗状态失败");
                return false;
            }
        }
        if(arg.Get("Tr2Bpi", setting))
        {
            uint bpi = ArgConvert::FromString<uint>(setting);
            MagneticDevAdapter::Track2BpiMode mode = (bpi == 210) ? MagneticDevAdapter::Bpi210 : MagneticDevAdapter::Bpi75;
            if(!MagneticDevAdapter::SetTrack2BPI(_pDev, mode))
            {
                _logErr(DeviceError::OperatorErr, "设置BPI失败");
                return false;
            }
        }
        if(arg.Get("TrElectric", setting))
        {
            uint e = ArgConvert::FromString<uint>(setting);
            if(!MagneticDevAdapter::SetTrElectric(_pDev, e))
            {
                _logErr(DeviceError::OperatorErr, "设置写磁头电流失败");
                return false;
            }
        }
        return true;
    }
    /**
     * @brief 读磁条
     * @date 2016-06-12 17:13
     * 
     * @param [in] Timeout : uint [default:DEV_WAIT_TIMEOUT] 等待刷卡的超时时间(ms)
     * @param [in] Mode : string [default:2] 磁条模式("23", "2", "123")
     * - 子参数:
     *  - 0:读出卡号
     *  - 1:需要读一磁道
     *  - 2:需要读二磁道
     *  - 3:需要读三磁道
     * .
     * @param [in] IsCheck : bool [default:true] 是否硬件校验
     * 
     * @retval CardNumber : string 卡号(从二磁道里面截取)
     * @retval Tr1 : string 一磁道数据
     * @retval Tr2 : string 二磁道数据
     * @retval Tr3 : string 三磁道数据
     */
    LC_CMD_METHOD(MagRead)
    {
        uint timeoutMs = arg["Timeout"].To<uint>(DEV_WAIT_TIMEOUT);
        string mode = arg["Mode"].To<string>("2");
        bool isCheck = arg["IsCheck"].To<bool>(true);
        
        _timerAdapter.SetWaitTimeout(timeoutMs);
        _magAdapter.IsCheckRetStatus = isCheck;

        ByteBuilder tr1(128);
        ByteBuilder tr2(128);
        ByteBuilder tr3(128);
        DevHelper::ErrEnum err = MagneticDevAdapterHelper::ReadMagneticCard(_magAdapter, mode.c_str(), &tr1, &tr2, &tr3);
        switch(err)
        {
        case DevHelper::EnumERROR:
            _logErr(DeviceError::ArgFormatErr, "磁条模式错误");
            return false;
        case DevHelper::EnumSUCCESS:
            break;
        default:
            return false;
        }
        if(StringConvert::ContainsChar(mode.c_str(), '0'))
        {
            ByteBuilder cardNumber(20);
            size_t index = StringConvert::IndexOf(tr2, '=');
            if(index == SIZE_EOF)
            {
                index = StringConvert::IndexOf(tr2, '\'');
            }
            cardNumber = tr2.SubArray(0, index);
            rlt.Put("CardNumber", cardNumber.GetString());
        }
        rlt.Put("Tr1", tr1.GetString());
        rlt.Put("Tr2", tr2.GetString());
        rlt.Put("Tr3", tr3.GetString());
        return true;
    }
    /**
     * @brief 写磁条
     * @date 2016-06-12 17:15
     * 
     * @param [in] Timeout : uint [default:DEV_WAIT_TIMEOUT] 等待刷卡的超时时间(ms)
     * @param [in] Mode : string 磁条模式("23", "2", "123")
     * - 子参数:
     *  - 1:需要写一磁道
     *  - 2:需要写二磁道
     *  - 3:需要写三磁道
     * .
     * @param [in] Tr1 : string 需要写入的一磁道数据
     * @param [in] Tr2 : string 需要写入的二磁道数据
     * @param [in] Tr3 : string 需要写入的三磁道数据
     * @param [in] IsCheck : bool [default:true] 是否硬件校验
     */
    LC_CMD_METHOD(MagWrite)
    {
        uint timeoutMs = arg["Timeout"].To<uint>(DEV_WAIT_TIMEOUT);
        string mode;
        if(!arg["Mode"].Get<string>(mode))
        {
            _logErr(DeviceError::ArgErr, "缺少参数:[Mode]");
            return false;
        }
        bool isCheck = arg["IsCheck"].To<bool>(true);
        string tr1 = arg["Tr1"].To<string>();
        string tr2 = arg["Tr2"].To<string>();
        string tr3 = arg["Tr3"].To<string>();

        _timerAdapter.SetWaitTimeout(timeoutMs);
        _magAdapter.IsCheckRetStatus = isCheck;

        DevHelper::ErrEnum err = MagneticDevAdapterHelper::WriteMagneticCard(
            _magAdapter, mode.c_str(), tr1.c_str(), tr2.c_str(), tr3.c_str());
        switch(err)
        {
        case DevHelper::EnumERROR:
            _logErr(DeviceError::ArgFormatErr, "磁条模式错误");
            return false;
        case DevHelper::EnumSUCCESS:
            break;
        default:
            return false;
        }
        return true;
    }
    /// 清除磁条刷卡状态
    LC_CMD_METHOD(MagClear)
    {
        return _pDev->Write(DevCommand::FromAscii("1B 30"));
    }
};
//--------------------------------------------------------- 
} // nemespace driver
} // namespace application
} // namespace zhou_yb
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_MAGNETICCMDDRIVER_H_
//========================================================= 